package cn.mg.framework.version;

import lombok.AllArgsConstructor;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.Assert;
import org.springframework.web.servlet.mvc.condition.RequestCondition;

import javax.servlet.http.HttpServletRequest;

/**
 * 获取请求的API版本
 */
@Getter
@AllArgsConstructor
public class ApiVersionCondition implements RequestCondition<ApiVersionCondition> {


    private static final String VERSION_SEPARATOR = ".";
    private static final int VERSION_LENGTH = 3;

    private String apiVersion;

    @Override
    public ApiVersionCondition combine(ApiVersionCondition other) {
        // 采用最后定义优先原则，则方法上的定义覆盖类上面的定义
        return new ApiVersionCondition(other.getApiVersion());
    }

    @Override
    public ApiVersionCondition getMatchingCondition(HttpServletRequest request) {
        String version = AppRequestUtils.apiVersion(request);
        if (StringUtils.isNoneEmpty(version) && compareVersion(version) > -1) {
            return this;
        }
        return null;
    }

    @Override
    public int compareTo(ApiVersionCondition other, HttpServletRequest request) {
        // 优先匹配最新的版本号
        if (other == null || StringUtils.isEmpty(other.getApiVersion())) {
            return StringUtils.isEmpty(this.apiVersion) ? 0 : 1;
        }
        if (StringUtils.isEmpty(this.apiVersion)) {
            return -1;
        }
        int result = compareVersion(other.getApiVersion());
        return result;
    }

    private int compareVersion(String otherVersion) {
        try {
            String[] thisVersions = StringUtils.split(this.apiVersion, VERSION_SEPARATOR);
            String[] otherVersions = StringUtils.split(otherVersion, VERSION_SEPARATOR);
            Assert.isTrue(VERSION_LENGTH == thisVersions.length, "Version has not correct Pattern");
            Assert.isTrue(VERSION_LENGTH == otherVersions.length, "Version has not correct Pattern");

            int thisVer;
            int otherVer;
            int result;
            for (int i = 0; i < VERSION_LENGTH; i++) {
                thisVer = Integer.valueOf(thisVersions[i]);
                otherVer = Integer.valueOf(otherVersions[i]);
                result = otherVer - thisVer;
                if (0 != result) {
                    return result;
                }
            }
            return 0;
        } catch (Exception e) {
            throw new IllegalStateException("Cannot compare Api-Version without correct Pattern.", e);
        }
    }
}